package com.kmzx.one.project.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.kmzx.one.common.constants.Constants;
import com.kmzx.one.common.utils.HttpClientUtil;
import com.kmzx.one.common.utils.StringUtils;
import com.kmzx.one.common.utils.UUIDGenerator;
import com.kmzx.one.project.config.data.WXDataConfig;
import com.kmzx.one.project.mapper.SimpleMapper;
import com.kmzx.one.project.others.dso.OutUserOrder;
import com.kmzx.one.project.others.dto.WikiPayRequest;
import com.kmzx.one.project.others.dto.WikiPayResponse;
import com.kmzx.one.project.service.ZOutService;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.text.StrBuilder;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;

@Service
public class ZOutServiceImpl implements ZOutService {
    private static final org.slf4j.Logger logger = LoggerFactory.getLogger(ZOutServiceImpl.class);

    @Autowired
    SimpleMapper simpleMapper;

    @Autowired
    WXDataConfig wxDataConfig;

    @Autowired
    StringRedisTemplate stringRedisTemplate;


    @Override
    public Map<String, Object> receiveReq(String reqData, String clientIP) {
        JSONObject reqFile = JSONObject.parseObject(reqData);
        Map<String, String> mapKV = new HashMap<>();
        mapKV.put("a", "0");
        mapKV.put("c", "1");
        mapKV.put("e", "2");
        mapKV.put("g", "3");
        mapKV.put("i", "4");
        mapKV.put("k", "5");
        mapKV.put("m", "6");
        mapKV.put("o", "7");
        mapKV.put("q", "8");
        mapKV.put("s", "9");
        mapKV.put("u", ".");


        String orderCode = reqFile.getString("orderCode");
        List<OutUserOrder> outUserOrders = simpleMapper.selectOutUserOrderAll(orderCode);
        boolean hasMoney = false;
        BigDecimal orderMoney = null;
        if (outUserOrders != null && outUserOrders.size() > 0) {
            OutUserOrder outUserOrder = outUserOrders.get(0);
            Integer states = outUserOrder.getStates();
            if (states == 2) {
                Map<String, Object> hashMap = new HashMap<>();
                hashMap.put("code", "400");
                hashMap.put("msg", "订单号已存在");
                return hashMap;
            } else {
                orderMoney = outUserOrder.getOrderMoney();
                hasMoney = true;
            }

        }
        String charFee = reqFile.getString("charFee");
//        BigDecimal orderMoney = reqFile.getBigDecimal("orderMoney");
        if (orderCode != null && !"".equals(orderCode)) {

        } else {
            Map<String, Object> hashMap = new HashMap<>();
            hashMap.put("code", "400");
            hashMap.put("msg", "订单号码错误");
            return hashMap;
        }
        int length = charFee.length();
        if (length == 0) {
            Map<String, Object> hashMap = new HashMap<>();
            hashMap.put("code", "400");
            hashMap.put("msg", "订单金额错误");
            return hashMap;
        }
        char[] c = charFee.toCharArray();
        StrBuilder stb = new StrBuilder();
        for (int i = 0; i < length; i++) {
            System.out.println("c[i] = " + c[i]);
            String s = mapKV.get(String.valueOf(c[i]));
            stb.append(s);
        }
        System.out.println("stb = " + stb);


        String s = stb.toString();
        if (s.contains("..")) {
            Map<String, Object> hashMap = new HashMap<>();
            hashMap.put("code", "400");
            hashMap.put("msg", "订单金额错误");
            return hashMap;
        }
//        BigDecimal orderMoney = reqFile.getBigDecimal("orderMoney");

        try {
            if (!hasMoney) {
                orderMoney = new BigDecimal(s);
                orderMoney.setScale(2);
            }
        } catch (Exception e) {
            e.printStackTrace();
            Map<String, Object> hashMap = new HashMap<>();
            hashMap.put("code", "400");
            hashMap.put("msg", "订单金额错误");
            return hashMap;
        }
//
        if (BigDecimal.ZERO.compareTo(orderMoney) >= 0) {
            Map<String, Object> hashMap = new HashMap<>();
            hashMap.put("code", "400");
            hashMap.put("msg", "订单金额错误");
            return hashMap;
        }


        String merchantCode = reqFile.getString("merchantCode");
        String prodName = reqFile.getString("prodName");

        String callbackUrl = reqFile.getString("callbackUrl");
        String h5CallbackUrl = wxDataConfig.getH5CallbackUrl();
        int i = h5CallbackUrl.lastIndexOf("/");
        String substring = h5CallbackUrl.substring(0, i);
        h5CallbackUrl = substring + "/mpay/callback";

        WikiPayRequest payRequest = new WikiPayRequest();
        payRequest.setAppid(wxDataConfig.getAppId());
        payRequest.setMch_id(wxDataConfig.getMerchantNum());
        payRequest.setNonce_str(UUIDGenerator.generator());
        payRequest.setBody("订单号:" + orderCode + "\n" + "快美甄选平台");
        payRequest.setOut_trade_no(orderCode);
        //金额
        BigDecimal payMoney = orderMoney;
        DecimalFormat df = new DecimalFormat("#");
        String money = df.format(payMoney.multiply(new BigDecimal(100)));
        payRequest.setTotal_fee(Integer.parseInt(money));
        payRequest.setSpbill_create_ip(clientIP);
        payRequest.setNotify_url(h5CallbackUrl + "/" + orderCode);
        String s1 = "'h5_info':{'type':'Wap','wap_url':'" + wxDataConfig.getH5WapUrl() + "','wap_name': '" + wxDataConfig.getH5WapName() + "'}";

        payRequest.setScene_info(s1);

        //签名
        SortedMap<String, Object> map = new TreeMap();
        map.put("appid", payRequest.getAppid());
        map.put("mch_id", payRequest.getMch_id());
        map.put("nonce_str", payRequest.getNonce_str());
        map.put("body", payRequest.getBody());
        map.put("out_trade_no", payRequest.getOut_trade_no());
        map.put("total_fee", payRequest.getTotal_fee());
        map.put("spbill_create_ip", payRequest.getSpbill_create_ip());
        map.put("notify_url", payRequest.getNotify_url());
        map.put("trade_type", payRequest.getTrade_type());
        map.put("scene_info", s1);
        StringBuilder strb = new StringBuilder();
        Set<String> keySet = map.keySet();
        for (String key : keySet) {
            Object value = map.get(key);
            strb.append(key).append("=").append(value);
            strb.append("&");
        }

        strb.append("key=").append(wxDataConfig.getMerchantKey());
        String sign = DigestUtils.md5Hex(strb.toString()).toUpperCase();
        payRequest.setSign(sign);

        String xmlReq = payRequest.toXML();
        String req = xmlReq.replace("&apos;", "'");
        Date date = new Date();
        logger.info("请求微信h5支付的数据为:{}", req);

        if (!hasMoney) {
            OutUserOrder userOrder = new OutUserOrder();
            userOrder.setId(UUIDGenerator.generate())
                    .setCreateTime(date).setUpdateTime(date)
                    .setOrderCode(orderCode).setOrderMoney(orderMoney)
                    .setMerchantNum(merchantCode).setMoneyString(charFee)
                    .setProdName(prodName).setStates(1).setNotifyResult(1)
                    .setNotifyTimes(0).setNotifyUrl(callbackUrl)
                    .setNextNotifyTime(null);

            simpleMapper.insertOutUserOrder(userOrder);
            logger.info("新增外部订单OK{}", userOrder);
        } else {
            logger.info("外部订单请求支付,更新,{}", orderCode);
        }




        String res = HttpClientUtil.postXmlBody(wxDataConfig.getPayUrl(), req);
        if (!StringUtils.isEmpty(res)) {
            WikiPayResponse wikiPayResponse = (WikiPayResponse) WikiPayResponse.fromXML(res);
            if (null != wikiPayResponse) {
                if ("SUCCESS".equals(wikiPayResponse.getReturn_code()) && "SUCCESS".equals(wikiPayResponse.getResult_code())) {
                    wikiPayResponse.getPrepay_id();
                    wikiPayResponse.getMweb_url();
                    Map<String, Object> hashMap = new HashMap<>();
                    String[] split = wikiPayResponse.getMweb_url().split("\\?");
                    hashMap.put("code", "200");
                    hashMap.put("reqUrl", wxDataConfig.getH5WapUrl() + "?money=" + orderMoney + "&orderCodes=" + orderCode + "&" + split[1]);
                    return hashMap;
                } else {
                    Map<String, Object> hashMap = new HashMap<>();
                    hashMap.put("code", "400");
                    hashMap.put("msg", "参数错误");
                    return hashMap;
                }
            } else {
                Map<String, Object> hashMap = new HashMap<>();
                hashMap.put("code", "400");
                hashMap.put("msg", "参数错误");
                return hashMap;
            }

        } else {
            Map<String, Object> hashMap = new HashMap<>();
            hashMap.put("code", "400");
            hashMap.put("msg", "参数错误");
            return hashMap;
        }
    }

    @Override
    public void resolveOutOrder(String orderCode, String req,String xmlResp) {
        List<OutUserOrder> outUserOrders = simpleMapper.selectOutUserOrderAll(orderCode);
        if (outUserOrders != null && outUserOrders.size() > 0) {
            OutUserOrder outUserOrder = outUserOrders.get(0);
            Integer states = outUserOrder.getStates();
            if (states == 2) {
                logger.info("订单已经支付成功");
            } else if (states == 1) {
                if ("SUCCESS".equals(req)) {
                    outUserOrder.setStates(2).setUpdateTime(new Date());
                    outUserOrder.setWxResp(xmlResp);
                    simpleMapper.updateUserOrderOut(outUserOrder);
                    stringRedisTemplate.opsForValue().set(Constants.out_user_order_prefix + outUserOrder.getId(), orderCode, 500, TimeUnit.MICROSECONDS);
                    logger.info("更新外部订单....,支付成功");
                } else if ("FAIL".equals(req)) {
                    outUserOrder.setStates(3).setUpdateTime(new Date());
                    simpleMapper.updateUserOrderOut(outUserOrder);
                    logger.info("更新外部订单....,支付失败");
                }
            }
        }
    }
}
